<template>
  <el-container>
    <el-aside width="300px" v-loading="menuLoading">
      <el-container>
        <el-header>
          <el-input placeholder="输入关键字进行过滤" v-model="menuFilterText" clearable></el-input>
        </el-header>
        <el-main class="nopadding">
          <el-tree ref="menuRef" class="menu" node-key="uuid" :data="menuList" :props="menuProps" draggable
                   highlight-current
                   :expand-on-click-node="false"
                   check-strictly show-checkbox :filter-node-method="menuFilterNode"
                   @node-click="menuClick" @node-drop="nodeDrop">
            <template #default="{node, data}">
							<span class="custom-tree-node">
								<span class="label">
									{{ node.label }}
								</span>
								<span class="do">
									<el-button icon="el-icon-plus" size="small" @click.stop="add(node, data)"></el-button>
								</span>
							</span>
            </template>
          </el-tree>
        </el-main>
        <el-footer style="height:51px;">
          <el-button v-auth="'setting:menu:add'" type="primary" size="small" icon="el-icon-plus"
                     @click="add()"></el-button>
          <el-button v-auth="'setting:menu:del:batch'" type="danger" size="small" plain icon="el-icon-delete"
                     @click="delMenu"></el-button>
          <el-button type="primary" size="small" icon="el-icon-ArrowDown"
                     @click="expandAll()">展开
          </el-button>
          <el-button type="primary" size="small" icon="el-icon-ArrowUp"
                     @click="collapseAll()">折叠
          </el-button>
        </el-footer>
      </el-container>
    </el-aside>
    <el-container>
      <el-main class="nopadding" style="padding:20px;" ref="mainRef">
        <save ref="saveRef" @success="handleSuccess" :menu="menuList"></save>
      </el-main>
    </el-container>
  </el-container>
</template>

<script setup name="settingMenu">
import save from './save'
import Apis from '@/api'
import {nextTick, onMounted, reactive, ref, watch} from "vue";
import {ElMessage, ElMessageBox} from "element-plus";


let menuLoading = ref(false)
let menuList = reactive([])
let menuProps = {
  label: (data) => {
    return data.meta.title
  }
}
let menuFilterText = ref("")

let menuRef = ref()
let saveRef = ref()
let mainRef = ref()

watch(() => menuFilterText, (val) => {
  menuRef.value.filter(val);
})

onMounted(() => {
  nextTick(() => {
    getMenu()
  })
})

// 展开所有节点
const expandAll = () => {
  menuRef.value.store._getAllNodes().forEach(node => {
    node.expanded = true;
  })
}
// 折叠所有节点
const collapseAll = () => {
  menuRef.value.store._getAllNodes().forEach(node => {
    node.expanded = false;
  })
}
//加载树数据
const getMenu = async () => {
  menuLoading.value = true
  let res = await Apis.api_setting.menu.list_all.get();
  menuLoading.value = false
  if (res.code === 0) {
    Object.assign(menuList, res.data)
  } else {
    ElMessage.error(res.message)
  }
}
//树点击
const menuClick = (data, node) => {
  let pid = node.level === 1 ? undefined : node.parent.data.id;
  saveRef.value.setData(JSON.parse(JSON.stringify(data)), pid)
  mainRef.value.$el.scrollTop = 0
}
//树过滤
const menuFilterNode = (value, data) => {
  if (!value) return true;
  let targetText = data.meta.title;
  return targetText.indexOf(value) !== -1;
}
//树拖拽
const nodeDrop = (draggingNode, dropNode, dropType) => {
  saveRef.value.setData({})
  ElMessage.info(`拖拽对象：${draggingNode.data.meta.title}, 释放对象：${dropNode.data.meta.title}, 释放对象的位置：${dropType}`)
}
//增加
const add = async (node, data) => {
  let newMenuName = "未命名" + new Date();
  let newMenuData = {
    uuid: '',
    menuParentId: data ? data.uuid : "",
    path: '/' + new Date(),
    name: newMenuName,
    component: '',
    meta: {
      title: newMenuName,
      type: 'menu',
    },
  };
  menuLoading.value = true
  let res = await Apis.api_setting.menu.create.post(newMenuData);
  menuLoading.value = false
  if (res.code === 0) {
    newMenuData.uuid = res.data.uuid
    menuRef.value.append(newMenuData, node)
    menuRef.value.setCurrentKey(newMenuData.uuid)
    let pid = node ? node.data.id : "";
    saveRef.value.setData(newMenuData, pid)
  } else {
    ElMessage.error(res.message)
  }
}
//删除菜单
const delMenu = async () => {
  let CheckedNodes = menuRef.value.getCheckedNodes();
  if (CheckedNodes.length === 0) {
    ElMessage.warning("请选择需要删除的项")
    return false;
  }

  let confirm = await ElMessageBox.confirm('确认删除已选择的菜单吗？', '提示', {
    type: 'warning',
    confirmButtonText: '删除',
    confirmButtonClass: 'el-button--danger'
  }).catch(() => {
  });
  if (confirm !== 'confirm') {
    return false
  }

  CheckedNodes.forEach(item => {
    let node = menuRef.value.getNode(item.uuid);
    if (node.childNodes.length > 0) {
      ElMessage.warning("请先删除子菜单")
      return false
    }
  })

  menuLoading.value = true
  let res = await Apis.api_setting.menu.del.post({
    uuid: CheckedNodes.map(item => item.uuid)
  });
  menuLoading.value = false
  if (res.code === 0) {
    CheckedNodes.forEach(item => {
      let node = menuRef.value.getNode(item);
      if (node.isCurrent) {
        saveRef.value.setData({})
      }
      menuRef.value.remove(item)
    })
    ElMessage.success("删除成功")
  } else {
    ElMessage.warning(res.message)
  }
}
//本地更新数据
const handleSuccess = (data) => {
  menuRef.value.data.filter(item => item.uuid === data.uuid).forEach(item => {
    Object.assign(item, JSON.parse(JSON.stringify(data)))
  })
}

</script>

<style scoped>
.menu:deep(.el-tree-node__label) {
  display: flex;
  flex: 1;
  height: 100%;
}

.custom-tree-node {
  display: flex;
  flex: 1;
  align-items: center;
  justify-content: space-between;
  font-size: 14px;
  height: 100%;
  padding-right: 24px;
}

.custom-tree-node .label {
  display: flex;
  align-items: center;;
  height: 100%;
}

.custom-tree-node .label .el-tag {
  margin-left: 5px;
}

.custom-tree-node .do {
  display: none;
}

.custom-tree-node .do i {
  margin-left: 5px;
  color: #999;
}

.custom-tree-node .do i:hover {
  color: #333;
}

.custom-tree-node:hover .do {
  display: inline-block;
}
</style>
